/*
	Visp is an opensource visual performance application built with Adobe® AIR™.
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
	
	Mike Creighton can be found at http://www.mikecreighton.com	
*/
package com.visp
{
	import com.visp.constants.*;
	import com.visp.events.BangEvent;
	import com.visp.events.DisplayMouseEvent;
	import com.visp.events.FilterLayerEvent;
	import com.visp.events.RendererEvent;
	import com.visp.events.RendererRequestEvent;
	import com.visp.events.TransitionEvent;
	import com.visp.filters.FilterManager;
	import com.visp.input.InputManager;
	import com.visp.midi.ControllerEvent;
	import com.visp.midi.MidiManager;
	import com.visp.midi.NoteEvent;
	import com.visp.midi.ProgramChangeEvent;
	import com.visp.render.Layer;
	import com.visp.render.RenderManager;
	import com.visp.transitions.TransitionManager;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.NativeWindow;
	import flash.display.NativeWindowInitOptions;
	import flash.display.NativeWindowSystemChrome;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.NativeWindowBoundsEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	import flash.utils.setTimeout;
	
	import mx.collections.ArrayCollection;
	import mx.modules.ModuleLoader;
	import com.visp.events.ColorEvent;
	
	[Event(name="previewToggle", type="com.visp.input.TogglePreviewRenderEvent")]
	[Event(name="toggle", type="com.visp.input.ScreenClearAlphaEvent")]
	[Event(name="alphaUpdate", type="com.visp.input.ScreenClearAlphaEvent")]
	[Event(name="unload", type="com.visp.input.UnloadLayerEvent")]
	[Event(name="select", type="com.visp.input.LayerSelectEvent")]
	[Event(name="midiSelect", type="com.visp.input.LayerSelectEvent")]
	[Event(name="slider", type="com.visp.input.SliderEvent")]
	[Event(name="moveUp", type="com.visp.input.ChangeLayerOrderEvent")]
	[Event(name="moveDown", type="com.visp.input.ChangeLayerOrderEvent")]
	
	public class VispShell extends EventDispatcher
	{
		private static var _instance : VispShell;
		private var _midiMgr : MidiManager;
		private var _rendererMgr : RenderManager;
		private var _filterMgr : FilterManager;
		private var _transitionMgr : TransitionManager;
		private var _inputMgr : InputManager;
		private var _timer : Timer;
		private var _delay : Timer;
		
		private var _drawSprite : Sprite;
		private var _drawBitmapData : BitmapData;
		private var _outputBitmapData : BitmapData;
		private var _outputWindowBitmap : Bitmap;
		private var _x : int;
		
		private var _outputWindow : NativeWindow;
		private var _outputWindowDelay : Timer;
		
		public static function getInstance() : VispShell {
			if(VispShell._instance == null){
				VispShell._instance = new VispShell();
			}
			return _instance;
		}
		
		public function VispShell() { }
		
		public function initialize() : void {
			this._midiMgr = MidiManager.getInstance();
			this._midiMgr.initialize();
			
			this._rendererMgr = new RenderManager();
			
			this._inputMgr = InputManager.getInstance();
			
			this._transitionMgr = TransitionManager.getInstance();
			this._transitionMgr.addEventListener(TransitionEvent.REMOVED, this._rendererMgr.handleRemovedTransition);
			this._transitionMgr.addEventListener(TransitionEvent.EXPIRED, this._rendererMgr.handleExpiredTransition);
			this._transitionMgr.initialize();
			
			this._filterMgr = FilterManager.getInstance();
			ROOT.filtersPanel.addEventListener(FilterLayerEvent.UPDATE, this._filterMgr.updateFilters);
			
			ROOT.previewOutput.init(RenderManager.outputBitmapData);
			ROOT.previewOutput.addEventListener(RendererEvent.NEW_RENDERER, this._rendererMgr.queueLayer);
			ROOT.previewOutput.addEventListener(DisplayMouseEvent.MOUSE_CLICK, this._inputMgr.handleDisplayMouseInput);
			ROOT.previewOutput.addEventListener(DisplayMouseEvent.DOWN, this._inputMgr.handleDisplayMouseInput);
			ROOT.previewOutput.addEventListener(DisplayMouseEvent.UP, this._inputMgr.handleDisplayMouseInput);
			ROOT.previewOutput.addEventListener(DisplayMouseEvent.DOWN_MOVE, this._inputMgr.handleDisplayMouseInput);
			
			ROOT.mediaPanel.addEventListener(RendererRequestEvent.NEW_RENDERER, ROOT.previewOutput.handleNewRendererRequest);
			
			
			STAGE.addEventListener(Event.ENTER_FRAME, _rendererMgr.render); // Create a callback for the main render call
			STAGE.addEventListener(Event.ENTER_FRAME, ROOT.fps.update); // Provide a FPS update display
		}
	}
}
